#include "stdafx.h"
#include "PythonApiHelpers.h"

std::string PythonApiHelpers::GetErrorMessage() {
	std::string message;
	
	PyObject* type = NULL;
	PyObject* value = NULL;
	PyObject* traceback = NULL;
	
	PyObject* errorOccurred = PyErr_Occurred();
	if(errorOccurred == Py_False) {
		Py_DECREF(errorOccurred);
		return message;
	}

	PyErr_Fetch(&type, &value, &traceback);

	if(value) {
		//Sometimes Python doesn't return a full error object
		// when you call PyErr_Fetch(). This fixes that.
		PyErr_NormalizeException(&type, &value, &traceback);

		//Print out the name of the Exception class if it is available.
		if(PyObject_HasAttrString(value, "__class__")) {
			PyObject* __class__ = PyObject_GetAttrString(value, "__class__");
			PyObject* __name__ = NULL;
			
			__name__ = PyObject_GetAttrString(__class__, "__name__");

			if(__name__ && PyString_Check(__name__)) {
				message.append(PyString_AsString(__name__));
				message.append(":");
			}

			Py_DECREF(__class__);
			Py_XDECREF(__name__);
		}

		//Print the error message.
		PyObject* valueString = NULL;
		valueString = PyObject_Str(value);
		
		if(valueString && PyString_Check(valueString)) {
			if(0 != message.length()) {
				message.append(" ");
			}
			
			message.append(PyString_AsString(valueString));
		}
		Py_XDECREF(valueString);
	}

	//Try to print the traceback, if it is available.
	if(traceback) {
		//The only use I've ever had for static locals. ;)
		static PyObject* tracebackModule = PyImport_ImportModule("traceback");
		static PyObject* methodName = PyString_FromString("format_tb");
		PyObject* tracebackList = PyObject_CallMethodObjArgs(tracebackModule, methodName, traceback, NULL);

		if(tracebackList) {
			if(0 != message.length()) {
				message.append("\r\n");
			}

			PyObject* iterator = PyObject_GetIter(tracebackList);

			PyObject* item;
			while(item = PyIter_Next(iterator)) {
				std::string tracebackLine(PyString_AsString(item));

				message.append(tracebackLine);
				Py_DECREF(item);
			}

			Py_DECREF(iterator);
		}

		Py_XDECREF(tracebackList);
	}

	Py_XDECREF(type);
	Py_XDECREF(value);
	Py_XDECREF(traceback);
	Py_DECREF(errorOccurred);

	return message;
}